package april;

import com.sun.deploy.util.StringUtils;

import java.util.Arrays;

/**
 * @author ：冯涛滔
 * @date ：Created in 2020-4-19 19:48
 * @description：
 * @modified By：
 * @version:
 */
public class April19 {
    public static void main(String[] args) {
//        System.out.println(getMaxRepetitions2("baba", 11, "baab", 1));
        String f = "冯";
        System.out.println("冯涛".length());
        System.out.println(f.codePointCount(0, f.length()));

    }
    /**
     * create by: 睚雪
     * description:
     * 1. 判断s2里有没有s1没有的字符
     * 2. 拼接字符串转换成数组
     * point 表示list2当前要比较的位置
     * last 表示上一次循环中和list[0]匹配成功的下标
     * 3. 循环list1
     * 如果point == 0 使用last记录当前位置
     * 如果匹配成功 point++
     * 判断point==list.length 代表list2的所有字符都判断完了 所以point重置 count++ 让i变成last
     * 判断到队尾i如果没有被再次重置的话就说明已经匹配完了
     * create time: 2020-4-19 20:50
     * @params [s1, n1, s2, n2]
     * @return int
     */
    public static int getMaxRepetitions(String s1, int n1, String s2, int n2) {

        //判断s2里的字符s1是否都有
        if(!check(s1,s2)){
            return 0;
        }
        boolean again = false; //判断需不需要再次遍历SS1
        int last = -1;
        int point = 0; //list2的指针
        int count = 0;
        StringBuffer buf =new StringBuffer();
        StringBuffer buf2 =new StringBuffer();

        //拼接s1
        for (int i = 0; i < n1; i++) {
            buf.append(s1);
        }
        //拼接s2
        for (int i = 0; i < n2; i++) {
            buf2.append(s2);
        }
        char[] list1 = buf.toString().toCharArray();
        char[] list2 = buf2.toString().toCharArray();
        //每次循环从上一个删除的开始位置开始 因为上一个位置一定是第一个符合ss2标准的所以之前的一定不会符合
        for (int i = 0; i < list1.length; i++) {
            if(list1[i]==list2[point]){
                list1[i] = '('; //给一个特别的字符让这个位置不可能再次匹配成功
                if(point==0){
                    last = i;
                }
                point++;//比较指针移动
                if(point==list2.length){ //一个数组比较完成了所以point重置
                    point = 0;
                    count++;
                    i = last;//让指针指向上次找到的第一个符合位置的下一个位置
                }
            }
        }
        return count;
    }
    public static int getMaxRepetitions2(String s1, int n1, String s2, int n2) {

        //判断s2里的字符s1是否都有
        if(!check(s1,s2)){
            return 0;
        }
        boolean again = false; //判断需不需要再次遍历SS1
        int last = -1;
        int point = 0; //list2的指针
        int count = 0;
        StringBuffer buf =new StringBuffer();
        StringBuffer buf2 =new StringBuffer();

        //拼接s1
        for (int i = 0; i < n1; i++) {
            buf.append(s1);
        }
        //拼接s2
        for (int i = 0; i < n2; i++) {
            buf2.append(s2);
        }
        char[] list1 = buf.toString().toCharArray();
        char[] list2 = buf2.toString().toCharArray();
        //每次循环从上一个删除的开始位置开始 因为上一个位置一定是第一个符合ss2标准的所以之前的一定不会符合
        for (int i = 0; i < list1.length; i++) {
            if(list1[i]==list2[point]){
                list1[i] = '('; //给一个特别的字符让这个位置不可能再次匹配成功
                point++;//比较指针移动
                if(point==list2.length){ //一个数组比较完成了所以point重置
                    point = 0;
                    count++;
                }
            }
        }
        return count;
    }
    /**
     * create by: 1
     * description: 判断在s2是否有s1不存在的字符
     * create time: \ 19:49
     * @params [s1, s2]
     * @return void
     */
    public static boolean check(String s1,String s2){
        char[] chars2 = s2.toCharArray();
        char[] chars1 = s1.toCharArray();
        for (int i = 0; i <chars2.length ; i++) {
            if (Arrays.asList(chars1).contains(chars2[i])) {
                return false;
            }
        }
        return true;
    }
    // 循环节
    public int getMaxRepetitions3(String s1, int n1, String s2, int n2) {
        int len1 = s1.length();
        int len2 = s2.length();
        // 特判
        if (len1 == 0 || len2 == 0 || n1 == 0 || n2 == 0) {
            return 0;
        }
        char[] chars1 = s1.toCharArray();
        char[] chars2 = s2.toCharArray();

        // 记录下一个要匹配的s2中字符的索引
        int index = 0;
        // 记录匹配完的s2个数
        int count = 0;
        // 记录在遍历每个s1时匹配出的s2的个数，可能是包含了前面一个s1循环节的部分
        int[] countRecorder = new int[n1];
        // 记录在每个s1中想要匹配的s2中字符的索引
        int[] indexRecorder = new int[n1];

        for (int i = 0; i < n1; ++i) {
            // 遍历s1
            for (int j = 0; j < len1; ++j) {
                // 匹配s2字符，匹配成功，s2索引+1
                if (chars1[j] == chars2[index]) {
                    ++index;
                }
                // 匹配完一个s2，计数器+1，重置s2索引
                if (index == chars2.length) {
                    index = 0;
                    ++count;
                }
            }
            // 记录遍历完i个s1后s2出现的次数
            countRecorder[i] = count;
            // 记录遍历完第i个s1后s2下一个要被匹配到的字符下标
            indexRecorder[i] = index;
            // 剪枝
            // 查看该索引在之前是否已出现，出现即表示已经出现循环节，可以直接进行计算
            // 上一次出现该索引是在第j个s1中（同时可以说明第一个循环节的出现是从第j+1个s1开始的）
            for (int j = 0; j < i && indexRecorder[j] == index; ++j) {
                // preCount: 记录循环节出现之前的s2出现的个数
                int preCount = countRecorder[j];
                // patternCount: 记录所有循环节构成的字符串中出现s2的个数
                //      j代表的是循环节的位置 也看做 在构成循环节之前花了多少节
                //       n1-1-j 等于还有多少节可以用来构成循环节
                //      i-j i是当前第几结 j是构成循环节开始的节数 i-j = 构成一个循环节需要多少节
                //      (n1 - 1 - j) / (i - j): 还可以构成多少循环节个数
                //      countRecorder[i] - countRecorder[j]: 一个循环节中包含的s2个数
                int patternCount = ((n1 - 1 - j) / (i - j)) * (countRecorder[i] - countRecorder[j]);
                // remainCount: 记录剩余未构成完整循环节的部分出现的s2的个数
                //      (n1 - 1 - j) % (i - j)代表在构成循环节之后还剩多少节
                //       j代表构成第一个循环节之前有多少节
                //      j+(n1 - 1 - j) % (i - j) 就是将构成循环节之前的节数+生成完循环节之后剩余的节数
                //      countRecorder[j + (n1 - 1 - j) % (i - j)] - countRecorder[j];
                //      通过取模从已有循环节记录中查找，并减去循环节之前出现的次数
                int remainCount = countRecorder[j + (n1 - 1 - j) % (i - j)] - preCount;
                // 三者相加，即为出现的s2的总次数 构成循环节之前的次数+循环节会出现的次数+剩余的节里会出现的次数
                return (preCount + patternCount + remainCount) / n2;
            }
        }
        // 没有循环节的出现，相当于直接使用暴力法
        return countRecorder[n1 - 1] / n2;
    }
}
